package myTest.example

class AA {
    var name = "java"
    var price = 1024
    fun printInfo() {
        println("name is $name,price is $price")
    }
}

//let  it，返回自定义，扩展函数
//run  this(可不写),返回自定义，扩展函数
//with  this(可不写),返回自定义
//apply this(可不写),返回自身，扩展函数
//also it,返回自身，扩展函数
fun main() {

    //在let块内可以通过 it 指代该对象。返回值为let块的最后一行或指定return表达式。
    //如果let块中的最后一条语句是非赋值语句，则默认情况下它是返回语句
    // inline fun <T, R> T.let(block: (T) -> R): R
    println(AA().let {
        it.name = "php"
        "change AA name is ${it.name}"
    })

    //run 有两种声明方式
    //1.与let一样，run是作为T的扩展函数   inline fun <T, R> T.run(block: T.() -> R): R
    println(
        AA().run {
            printInfo()
            name = "kotlin"
            price = 2048
            "change AA name is $name,price is $price"
        }
    )

    //2.run函数块执行方法，而不是作为一个扩展函数 inline fun <R> run(block: () -> R): R
    run {
        val aa = AA()
        aa.name = ".net"
        aa
    }.printInfo()

    //with属于非扩展函数，直接输入一个对象receiver，当输入receiver后，便可以更改receiver的属性，同时，它也与run做着同样的事情
    //inline fun <T, R> with(receiver: T, block: T.() -> R): R
    println(with(AA()){
        name = "c++"
        "return string is $name"
    })

    // this,apply不接受函数块中的返回值，返回的是自己的T类型对象
    //inline fun <T> T.apply(block: T.() -> Unit): T
    AA().apply {
        name = "python"
        price = 1000
    }.printInfo()

    //it,不接受函数块中的返回值，返回的是自己的T类型对象
    //inline fun <T> T.also(block: (T) -> Unit): T
    AA().also {
        it.name = "js"
        it.price = 1
    }.printInfo()
}
